package com.recharge.service.impl;

import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.recharge.common.util.ArithUtils;

import com.recharge.common.util.ListUtil;
import com.recharge.core.entity.GoodsMerchantEntity;
import com.recharge.core.entity.GoodsProviderEntity;
import com.recharge.core.mapper.GoodsMapper;
import com.recharge.core.mapper.GoodsMerchantMapper;
import com.recharge.domain.vo.GoodsDO;
import com.recharge.domain.vo.GoodsMerchantDO;
import com.recharge.domain.vo.GoodsProviderDO;
import com.recharge.service.GoodsMerchantService;
import com.recharge.service.GoodsProviderService;
import com.recharge.service.GoodsService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.recharge.common.domain.PageDO;
import com.recharge.common.enums.ErrorCode;
import com.recharge.common.result.ResultDO;
import com.recharge.common.result.ResultSupport;
import com.recharge.common.util.BeanUtilsExtends;
import com.recharge.common.util.Constant;
import com.recharge.core.entity.GoodsEntity;
import com.recharge.core.entity.GoodsGroupEntity;
import com.recharge.core.mapper.GoodsGroupMapper;
import com.recharge.domain.query.GoodsGroupQueryDO;
import com.recharge.domain.vo.GoodsGroupDO;
import com.recharge.service.GoodsGroupService;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

/**
 * <p>
 * 商品分组 服务实现类
 * </p>
 *
 * @author reagan
 * @since 2020-08-19
 */
@Service
public class GoodsGroupServiceImpl extends ServiceImpl<GoodsGroupMapper, GoodsGroupEntity> implements GoodsGroupService {

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    @Autowired
    private GoodsService goodsService;
    @Autowired
    private GoodsMerchantService goodsMerchantService;
    @Autowired
    private GoodsProviderService goodsProviderService;
    
    public ResultDO add(GoodsGroupDO domain) {

        GoodsGroupEntity entity = new GoodsGroupEntity();

        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        entity.setCreateDate(Calendar.getInstance().getTime());
        entity.setModifiDate(entity.getCreateDate());
        entity.setModifier(entity.getCreator());
        boolean res = false;
        try {
            res = this.save(entity);
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(!res) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.GOODS_ADD_GROUP_ERROR);
            logger.debug("error code：" + ErrorCode.GOODS_ADD_GROUP_ERROR.getCode() + " msg" + ErrorCode.GOODS_ADD_GROUP_ERROR.getMsg());
            return result;
        }

        return result;
    }

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
    public ResultDO edit(GoodsGroupDO domain) {

        GoodsGroupEntity entity = new GoodsGroupEntity();

        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        entity.setModifiDate(Calendar.getInstance().getTime());
        //修改该商品组中的商品在与代理商关联中的所有价格折扣等信息 TODO 目前是都按照即时生效的方式处理
//        List<GoodsEntity> goodsList = null;//
//
//        try {
//            goodsList = goodsService.findByGroupId(domain.getId());//goodsMapper.selectList(Wrappers.<GoodsEntity>lambdaQuery().eq(GoodsEntity::getGroupId, domain.getId()).eq(GoodsEntity::getIsDelete, Constant.IS_DELETE_FALSE));
//        } catch (Exception e) {
//            result.setSuccess(false);
//            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
//            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return result;
//        }

        result = goodsService.findByGroupId(domain.getId());
        if(!result.isSuccess()){
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }

        List<GoodsDO> goodsList = (List<GoodsDO>) result.getModel(ResultDO.FIRST_MODEL_KEY);

        if(goodsList != null && !goodsList.isEmpty()) {
            if (domain.getUnit() == Constant.UNIT_SCALE) {
//                int count = 1;
//                if (goodsList.size() % 100 == 0) {
//                    count = goodsList.size() / 100;
//                } else {
//                    count = goodsList.size() / 100 + 1;
//                }
//                List<List<GoodsEntity>> listAll = ListUtil.split(goodsList, count);
//                for (List<GoodsEntity> li : listAll) {
//                    if (li != null && !li.isEmpty()) {
//                        GoodsMerchantEntity goodsMerchantEntity = new GoodsMerchantEntity();
//                        goodsMerchantEntity.setDiscount((float)ArithUtils.div(Double.parseDouble(String.valueOf(domain.getValueData())), 10000));
//                        try {
//                            goodsMerchantMapper.update(goodsMerchantEntity, Wrappers.<GoodsMerchantEntity>lambdaQuery().in(GoodsMerchantEntity::getGoodsId, li.stream().map(GoodsEntity::getId).collect(Collectors.toList())));
//                        } catch (Exception e) {
//                            result.setSuccess(false);
//                            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
//                            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
//                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//                            return result;
//                        }
//                    }
//                }
                try {
                    GoodsMerchantDO updateDomain = new GoodsMerchantDO();
                    updateDomain.setDiscount((float)ArithUtils.div(Double.parseDouble(String.valueOf(domain.getValueData())), 10000));
                    for (GoodsDO goods : goodsList) {
                        result = goodsMerchantService.editByGoodsId(updateDomain, goods.getId());
                        if(!result.isSuccess()){
                            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
                            throw new Exception();
                        }
//                        goodsMerchantMapper.update(goodsMerchantEntity, Wrappers.<GoodsMerchantEntity>lambdaQuery().eq(GoodsMerchantEntity::getGoodsId, goods.getId()));
                    }
                } catch (Exception e) {
                    result.setSuccess(false);
                    result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
                    logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return result;
                }
            }
        }

        boolean res = false;
        try {
            res = this.updateById(entity);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(!res) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.GOODS_EDIT_GROUP_ERROR);
            logger.debug("error code：" + ErrorCode.GOODS_EDIT_GROUP_ERROR.getCode() + " msg" + ErrorCode.GOODS_EDIT_GROUP_ERROR.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }
        return result;
    }

    
    public ResultDO get(String id) {

        ResultDO result = new ResultSupport();
        GoodsGroupEntity entity = null;

        try {
            entity = this.getById(id);
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        GoodsGroupDO domain = getDomain(entity);

        result.setModel(ResultDO.FIRST_MODEL_KEY, domain);

        return result;
    }


    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
    public ResultDO remove(String id, String modifier) {
        ResultDO result = new ResultSupport();

        GoodsGroupEntity entity = new GoodsGroupEntity();

        //判断商品组下面是否存在商品
        List<GoodsEntity> list = null;
        try {
            list = goodsService.list(Wrappers.<GoodsEntity>lambdaQuery().eq(GoodsEntity::getGroupId, id).eq(GoodsEntity::getIsDelete, Constant.IS_DELETE_FALSE));
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }

        if(list != null && list.size() > 0){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.GOODS_RELATED_GOODS_EXIST);
            logger.debug("error code：" + ErrorCode.GOODS_RELATED_GOODS_EXIST.getCode() + " msg" + ErrorCode.GOODS_RELATED_GOODS_EXIST.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }

        entity.setModifiDate(Calendar.getInstance().getTime());
        entity.setModifier(modifier);
        entity.setId(id);
        entity.setIsDelete(Constant.IS_DELETE);
        boolean res = false;
        try {
            //删除商品组下面的所有商品
            result = goodsService.removeByGroupId(id, modifier);
            if(result.isSuccess()){
                res = this.updateById(entity);
            }
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(!res) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.GOODS_DELETE_GROUP_ERROR);
            logger.debug("error code：" + ErrorCode.GOODS_DELETE_GROUP_ERROR.getCode() + " msg" + ErrorCode.GOODS_DELETE_GROUP_ERROR.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }

        return result;
    }

    
    public ResultDO find(GoodsGroupQueryDO query) {
    	GoodsGroupEntity entity = new GoodsGroupEntity();
        ResultDO result = BeanUtilsExtends.copy(entity, query);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        QueryWrapper<GoodsGroupEntity> wrapper = new QueryWrapper<GoodsGroupEntity>(entity);
        Page<GoodsGroupEntity> page = new Page<>(query.getCurrentPage(),query.getPageSize());
        if(StringUtils.isNotEmpty(query.getGroupName())){
            entity.setGroupName(null);
            wrapper.lambda().like(GoodsGroupEntity::getGroupName, query.getGroupName());
        }
        //有效的
        wrapper.lambda().eq(GoodsGroupEntity::getIsDelete, Constant.IS_DELETE_FALSE);
        IPage<GoodsGroupEntity> iPage = null;

        try {
            if(query.getIsRelated() != null && query.getIsRelated() == 1){
                wrapper.lambda().last("and bmg.id IS NULL");
                iPage = baseMapper.selectOtherPage(page, wrapper);
            } else {
                iPage = baseMapper.selectPage(page, wrapper);
            }
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }
        List<GoodsGroupDO> doList = getDomainList(iPage.getRecords());
        if(doList != null && doList.size() > 0){
            try {
                doList.stream().forEach( item -> {
                    GoodsDO selectDomain = new GoodsDO();
                    selectDomain.setGroupId(item.getId());
                    ResultDO selectResult = goodsService.selectCount(selectDomain);//goodsMapper.selectCount(Wrappers.<GoodsEntity>lambdaQuery().eq(GoodsEntity::getGroupId, item.getId()).eq(GoodsEntity::getIsDelete, Constant.IS_DELETE_FALSE));
                    if(!selectResult.isSuccess()){
                        logger.debug("error code：" + selectResult.getErrorCode().getCode() + " msg" + selectResult.getErrorCode().getMsg());
                    }
                    item.setGoodsCount((Integer) selectResult.getModel(ResultDO.FIRST_MODEL_KEY));
                });
            } catch (Exception e) {
                result.setSuccess(false);
                result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
                logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
                return result;
            }
        }
        PageDO<GoodsGroupDO> pageDO = new PageDO<>();

        pageDO.setCurrentPage(iPage.getCurrent());
        pageDO.setPageCount(iPage.getPages());
        pageDO.setPageSize(iPage.getSize());
        pageDO.setRowCount(iPage.getTotal());
        pageDO.setData(doList);

        result.setModel(ResultDO.FIRST_MODEL_KEY, pageDO);
        return result;
    }

    @Override
    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
    public void updateGoodsPriceTask() {
        List<GoodsGroupEntity> list = this.list(Wrappers.<GoodsGroupEntity>lambdaQuery()
                .eq(GoodsGroupEntity::getStatus, Constant.GOODS_GROUP_STATUS_1)
                .le(GoodsGroupEntity::getEnableDate, Calendar.getInstance().getTime()));
        if(list != null && !list.isEmpty()){
            List<String> idList = list.stream().map( item -> {
                GoodsEntity goodsEntity = new GoodsEntity();
                boolean flog = false;
                try {
                    flog = goodsService.update(goodsEntity, Wrappers.<GoodsEntity>lambdaQuery().eq(GoodsEntity::getGroupId, item.getId()));
                } catch (Exception e) {
                    logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    throw e;
                }
                if(flog){
                    return item.getId();
                }
                return "";
            }).filter(string -> !string.isEmpty()).collect(Collectors.toList());
            if(list != null && !list.isEmpty()){
                GoodsGroupEntity entity = new GoodsGroupEntity();
                entity.setStatus(Constant.GOODS_GROUP_STATUS_2);

//                int count = 1;
//                if (list.size() % 100 == 0) {
//                    count = list.size() / 100;
//                } else {
//                    count = list.size() / 100 + 1;
//                }
//                List<List<GoodsGroupEntity>> listAll = ListUtil.split(list, count);
//                for (List<GoodsGroupEntity> li : listAll) {
//                    if (li != null && !li.isEmpty()) {
//                        try {
//                            this.update(entity, Wrappers.<GoodsGroupEntity>lambdaQuery().in(GoodsGroupEntity::getStatus, li.stream().map(GoodsGroupEntity::getStatus).collect(Collectors.toList())));
//                        } catch (Exception e) {
//                            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
//                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//                            break;
//                        }
//                    }
//                }
                try {
                    for (GoodsGroupEntity group : list) {
                        baseMapper.update(entity, Wrappers.<GoodsGroupEntity>lambdaQuery().eq(GoodsGroupEntity::getStatus, group.getStatus()));
                    }
                } catch (Exception e) {
//                    result.setSuccess(false);
//                    result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
                    logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//                    return result;
                }
            }
        }
    }

    @Override
    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
    public ResultDO batchDisassociate(String id, String[] goodsIds, String userName) {
        ResultDO result = new ResultSupport();
        if(StringUtils.isEmpty(id) || goodsIds.length <= 0){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.PARAM_GET_ERROR);
            logger.debug("error code：" + ErrorCode.PARAM_GET_ERROR.getCode() + " msg" + ErrorCode.PARAM_GET_ERROR.getMsg());
            return result;
        }

        if(goodsIds != null && goodsIds.length > 1000){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.GOODS_OVERSTEP_MAX_NUM);
            logger.debug("error code：" + ErrorCode.GOODS_OVERSTEP_MAX_NUM.getCode() + " msg" + ErrorCode.GOODS_OVERSTEP_MAX_NUM.getMsg());
            return result;
        }

        GoodsDO goodsDO = new GoodsDO();
        goodsDO.setGroupId(null);
        result = goodsService.updateGoodsBatchById(goodsDO, Arrays.stream(goodsIds).collect(Collectors.toList()));
        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(!result.isSuccess()) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.GOODS_DISASSOCIATE_FAILURE);
            logger.debug("error code：" + ErrorCode.GOODS_DISASSOCIATE_FAILURE.getCode() + " msg" + ErrorCode.GOODS_DISASSOCIATE_FAILURE.getMsg());
            return result;
        }
        try {
            //取消对代理商的关联
            GoodsMerchantDO updateDomain = new GoodsMerchantDO();
            updateDomain.setModifier(userName);
            updateDomain.setIsDelete(Constant.IS_DELETE);

            for (String goodsId : goodsIds) {
                result = goodsMerchantService.removeByGoodsId(goodsId, userName);
                if(!result.isSuccess()){
                    logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
                    throw new Exception();
                }
            }
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }

//        try {
//            //取消对供货的关联
//            GoodsProviderDO updateDomain = new GoodsProviderDO();
//            updateDomain.setModifier(userName);
//            updateDomain.setIsDelete(Constant.IS_DELETE);
//
//            for (String goodsId : goodsIds) {
//                result = goodsProviderService.removeByGoodsId(goodsId, userName);
//                if(!result.isSuccess()){
//                    logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
//                    throw new Exception();
//                }
//            }
//        } catch (Exception e) {
//            result.setSuccess(false);
//            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
//            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return result;
//        }

        return result;
    }

    private GoodsGroupDO getDomain(GoodsGroupEntity entity) {

        //判断房源对象是否为空，为空就返回 空，不为空就进行下面的代码
        if(entity == null) return null;
        GoodsGroupDO domain = new GoodsGroupDO();

        domain = BeanUtilsExtends.copyProperties(domain, entity) ? domain : null;

        //判断拷贝数据到Dto对象是否成功，如果成功则返回domian，如果不成功就返回空
        return domain;
    }

    private List<GoodsGroupDO> getDomainList(List<GoodsGroupEntity> list) {
        //创建一个名为dolist的房源do类型的 list集合
        List<GoodsGroupDO> doList = new ArrayList<GoodsGroupDO>();

        //判断传入的list的集合的size是否大于0
        if(list.size() > 0) {
            //大于0是，遍历list，创建do类型的对象 调用getdomain方法
            for(GoodsGroupEntity entity : list) {

                GoodsGroupDO domain = this.getDomain(entity);

                //判断得到的domain 是否为空 不为空 就往dolist集合里面添加domian 为空就返回空
                if(domain == null) {
                    return null;
                }
                doList.add(domain);
            }
        } else {
            return null;
        }
        return doList;
    }
}
